let count = 0;

function noop() {
    
}

export function jsonp(url, opts, fn) {
    if ('function' === typeof opts) {
        fn = opts;
        opts = {};
    }
    if (!opts) opts = {};

    let prefix = opts.prefix || '__jp';

    // use the callback name that was passed if one was provided.
    // otherwise generate a unique name by incrementing our counter.
    let id = opts.name || (prefix + (count++));

    let param = opts.param || 'callback';
    let timeout = null !== opts.timeout ? opts.timeout : 60000;
    let enc = encodeURIComponent;
    let target = document.getElementsByTagName('script')[0] || document.head;
    let script;
    let timer;


    if (timeout) {
        timer = setTimeout(function(){
            cleanup();
            if (fn) fn(new Error('Timeout'));
        }, timeout);
    }

    function cleanup(){
        if (script.parentNode) script.parentNode.removeChild(script);
        window[id] = noop;
        if (timer) clearTimeout(timer);
    }

    function cancel(){
        if (window[id]) {
            cleanup();
        }
    }

    window[id] = function(data){
        cleanup();
        if (fn) fn(null, data);
    };

    // add qs component
    url += (~url.indexOf('?') ? '&' : '?') + param + '=' + enc(id);
    url = url.replace('?&', '?');


    // create script
    script = document.createElement('script');
    script.src = url;
    target.parentNode.insertBefore(script, target);

    return cancel;
}
